package com.hz.score.cus.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hz.score.common.dto.PageDto;
import com.hz.score.common.exception.ScoreException;
import com.hz.score.common.util.ConvertUtil;
import com.hz.score.cus.dto.CusCommLinkDto;
import com.hz.score.cus.dto.CusIndLinkDto;
import com.hz.score.cus.dto.CusInfoDto;
import com.hz.score.cus.mapper.CusCommLinkMapper;
import com.hz.score.cus.mapper.CusIndLinkMapper;
import com.hz.score.cus.mapper.CusInfoMapper;
import com.hz.score.cus.model.CusCommLink;
import com.hz.score.cus.model.CusIndLink;
import com.hz.score.cus.model.CusInfo;
import com.hz.score.ent.dto.EntCommInfoDto;
import com.hz.score.ent.service.EntService;
import com.hz.score.ind.dto.IndInfoDto;
import com.hz.score.ind.service.IndService;
import com.hz.score.msg.event.CusCommLinkEvent;
import com.hz.score.msg.event.CusCommUnlinkEvent;
import com.hz.score.msg.event.CusIndLinkEvent;
import com.hz.score.msg.event.CusIndUnlinkEvent;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CusService {

    @Resource
    CusInfoMapper cusInfoMapper;

    @Resource
    CusCommLinkMapper cusCommLinkMapper;

    @Resource
    CusIndLinkMapper cusIndLinkMapper;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    EntService entService;

    @Resource
    IndService indService;

    public PageDto<CusInfoDto> pageCus(CusInfoDto cusInfoDto, Integer pageSize, Integer pageNum) {
        QueryWrapper wrapper = new QueryWrapper();
        if (cusInfoDto.getBizTyp() != null) wrapper.eq("biz_typ", cusInfoDto.getBizTyp());
        return ConvertUtil.convertPage(cusInfoMapper.selectPage(new Page<>(pageNum, pageSize), wrapper), CusInfoDto.class);
    }

    public int newCus(CusInfoDto cusInfoDto) {
        CusInfo cusInfo = new CusInfo();
        BeanUtils.copyProperties(cusInfoDto, cusInfo);
        cusInfo.setBizTypCode(newBizTypCode(cusInfoDto.getParentBizTyp()));
        return cusInfoMapper.insert(cusInfo);
    }

    public int updateCus(CusInfoDto cusInfoDto) {
        CusInfo cusInfo = new CusInfo();
        BeanUtils.copyProperties(cusInfoDto, cusInfo);
        return cusInfoMapper.updateById(cusInfo);
    }

    public int delCus(CusInfoDto cusInfoDto) {
        CusInfo cusInfo = new CusInfo();
        BeanUtils.copyProperties(cusInfoDto, cusInfo);
        return cusInfoMapper.deleteById(cusInfo);
    }

    public CusInfoDto getCus(Long id) {
        CusInfo cusInfo =  cusInfoMapper.selectById(id);
        CusInfoDto cusInfoDto = new CusInfoDto();
        BeanUtils.copyProperties(cusInfo, cusInfoDto);
        return cusInfoDto;
    }

    public CusInfoDto getCusByBizTyp(String bizTyp) {
        CusInfo cusInfo =  cusInfoMapper.getByBizTyp(bizTyp);
        if (cusInfo != null) {
            CusInfoDto cusInfoDto = new CusInfoDto();
            BeanUtils.copyProperties(cusInfo, cusInfoDto);
            return cusInfoDto;
        }
        return null;
    }

    private String newBizTypCode(String bizTyp) {
        if (StringUtils.isEmpty(bizTyp)) {
            int count =  cusInfoMapper.getChildsCountIsnull();
            return String.format("%04d", count + 1);
        } else {
            CusInfo parentCusInfo = cusInfoMapper.getByBizTyp(bizTyp);
            if (parentCusInfo == null) {
                throw new ScoreException("parent biz do not exist");
            }
            int count =  cusInfoMapper.getChildsCountByBizTyp(bizTyp);
            return String.format("%s%04d", parentCusInfo.getBizTypCode(), count + 1);
        }
    }

    public List<CusInfoDto> getAllParentByBizTyp(String bizTyp) {
        CusInfo cusInfo = cusInfoMapper.getByBizTyp(bizTyp);
        List<CusInfo> parentList = cusInfoMapper.getAllParent(transformBizTypCodes(cusInfo.getBizTypCode()));
        return ConvertUtil.convertList(parentList, CusInfoDto.class);
    }

    private List<String> transformBizTypCodes(String bizTypCode) {
        List<String> result = new ArrayList<>();
        for (int i = 4; i <= bizTypCode.length(); i += 4) {
            result.add(bizTypCode.substring(0, i));
        }
        return result;
    }

    public List<CusInfoDto> getAllChild(String bizTyp) {
        CusInfo cusInfo = cusInfoMapper.getByBizTyp(bizTyp);
        if (cusInfo != null) {
            List<CusInfo> childList = cusInfoMapper.getAllChild(cusInfo.getBizTypCode());
            return ConvertUtil.convertList(childList, CusInfoDto.class);
        }
        return new ArrayList<>();
    }

    public PageDto<CusCommLinkDto> pageLinkComm(CusCommLinkDto cusCommLinkDto, Integer pageSize, Integer pageNum) {
        QueryWrapper wrapper = new QueryWrapper();
        if (cusCommLinkDto.getCusId() != null) wrapper.eq("cus_id", cusCommLinkDto.getCusId());
        if (cusCommLinkDto.getBizTyp() != null) wrapper.eq("biz_typ", cusCommLinkDto.getBizTyp());
        if (cusCommLinkDto.getCommId() != null) wrapper.eq("comm_id", cusCommLinkDto.getCommId());
        return ConvertUtil.convertPage(cusCommLinkMapper.selectPage(new Page<>(pageNum, pageSize), wrapper), CusCommLinkDto.class);
    }

    public List<CusCommLinkDto> listLinkComm(CusCommLinkDto cusCommLinkDto) {
        QueryWrapper wrapper = new QueryWrapper();
        if (cusCommLinkDto.getCusId() != null) wrapper.eq("cus_id", cusCommLinkDto.getCusId());
        if (cusCommLinkDto.getBizTyp() != null) wrapper.eq("biz_typ", cusCommLinkDto.getBizTyp());
        if (cusCommLinkDto.getCommId() != null) wrapper.eq("comm_id", cusCommLinkDto.getCommId());
        return ConvertUtil.convertList(cusCommLinkMapper.selectList(wrapper), CusCommLinkDto.class);
    }

    public CusCommLinkDto getLinkComm(Long cusId, Long commId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("cus_id", cusId);
        wrapper.eq("comm_id", commId);
        List<CusCommLink> cusCommLinkList = cusCommLinkMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(cusCommLinkList)) {
            return ConvertUtil.convert(cusCommLinkList.get(0), CusCommLinkDto.class);
        }
        return null;
    }

    public List<CusCommLinkDto> listLinkCommByBizTyes(List<String> bizTyps) {
        return ConvertUtil.convertList(cusCommLinkMapper.getAllCusCommLink(bizTyps), CusCommLinkDto.class);
    }

    public void linkComm(CusCommLinkDto cusCommLinkDto) {
        EntCommInfoDto entCommInfoDto = entService.getCommEnt(cusCommLinkDto.getCommId());
        if (entCommInfoDto == null) {
            throw new ScoreException("comm info do not exist");
        }
        CusInfo cusInfo = cusInfoMapper.selectById(cusCommLinkDto.getCusId());
        if (cusInfo == null) {
            throw new ScoreException("cus info do not exist");
        }
        CusCommLinkDto commLinkDtoOld = getLinkComm(cusCommLinkDto.getCusId(), cusCommLinkDto.getCommId());
        if (commLinkDtoOld != null) {
            throw new ScoreException("comm link info already exist");
        }
        CusCommLink cusCommLink = new CusCommLink();
        BeanUtils.copyProperties(cusCommLinkDto, cusCommLink);
        cusCommLinkMapper.insert(cusCommLink);
        CusCommLinkEvent cusCommLinkEvent = new CusCommLinkEvent(this);
        BeanUtils.copyProperties(cusCommLink, cusCommLinkEvent);
        applicationEventPublisher.publishEvent(cusCommLinkEvent);
    }
    public void unlinkComm(CusCommLinkDto cusCommLinkDto) {
        CusCommLinkDto commLinkDtoOld = getLinkComm(cusCommLinkDto.getCusId(), cusCommLinkDto.getCommId());
        if (commLinkDtoOld == null) {
            throw new ScoreException("comm link info do not exist");
        }
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("cus_id", cusCommLinkDto.getCusId());
        wrapper.eq("comm_id", cusCommLinkDto.getCommId());
        cusCommLinkMapper.delete(wrapper);
        CusCommUnlinkEvent cusCommUnlinkEvent = new CusCommUnlinkEvent(this);
        BeanUtils.copyProperties(commLinkDtoOld, cusCommUnlinkEvent);
        applicationEventPublisher.publishEvent(cusCommUnlinkEvent);
    }

    public PageDto<CusIndLinkDto> pageLinkInd(CusIndLinkDto cusIndLinkDto, Integer pageSize, Integer pageNum) {
        QueryWrapper wrapper = new QueryWrapper();
        if (cusIndLinkDto.getCusId() != null) wrapper.eq("cus_id", cusIndLinkDto.getCusId());
        if (cusIndLinkDto.getBizTyp() != null) wrapper.eq("biz_typ", cusIndLinkDto.getBizTyp());
        if (cusIndLinkDto.getIndId() != null) wrapper.eq("ind_id", cusIndLinkDto.getIndId());
        return ConvertUtil.convertPage(cusIndLinkMapper.selectPage(new Page<>(pageNum, pageSize), wrapper), CusIndLinkDto.class);
    }

    public List<CusIndLinkDto> listLinkInd(CusIndLinkDto cusIndLinkDto) {
        QueryWrapper wrapper = new QueryWrapper();
        if (cusIndLinkDto.getCusId() != null) wrapper.eq("cus_id", cusIndLinkDto.getCusId());
        if (cusIndLinkDto.getBizTyp() != null) wrapper.eq("biz_typ", cusIndLinkDto.getBizTyp());
        if (cusIndLinkDto.getIndId() != null) wrapper.eq("ind_id", cusIndLinkDto.getIndId());
        return ConvertUtil.convertList(cusIndLinkMapper.selectList(wrapper), CusIndLinkDto.class);
    }

    public CusIndLinkDto getLinkInd(Long cusId, Long indId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("cus_id", cusId);
        wrapper.eq("ind_id", indId);
        List<CusIndLinkDto> cusCommLinkList = cusIndLinkMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(cusCommLinkList)) {
            return ConvertUtil.convert(cusCommLinkList.get(0), CusIndLinkDto.class);
        }
        return null;
    }

    public List<CusIndLinkDto> listLinkIndByBizTyes(List<String> bizTyps) {
        return ConvertUtil.convertList(cusIndLinkMapper.getAllCusIndLink(bizTyps), CusIndLinkDto.class);
    }

    public void linkInd(CusIndLinkDto cusIndLinkDto) {
        IndInfoDto indInfoDto = indService.getIndEnt(cusIndLinkDto.getIndId());
        if (indInfoDto == null) {
            throw new ScoreException("ind info do not exist");
        }
        CusInfo cusInfo = cusInfoMapper.selectById(cusIndLinkDto.getCusId());
        if (cusInfo == null) {
            throw new ScoreException("cus info do not exist");
        }
        CusIndLinkDto cusIndLinkDtoOld = getLinkInd(cusIndLinkDto.getCusId(), cusIndLinkDto.getIndId());
        if (cusIndLinkDtoOld != null) {
            throw new ScoreException("ind link info already exist");
        }
        CusIndLink cusIndLink = new CusIndLink();
        BeanUtils.copyProperties(cusIndLinkDto, cusIndLink);
        cusIndLinkMapper.insert(cusIndLink);
        CusIndLinkEvent cusIndLinkEvent = new CusIndLinkEvent(this);
        BeanUtils.copyProperties(cusIndLinkDto, cusIndLinkEvent);
        applicationEventPublisher.publishEvent(cusIndLinkEvent);
    }
    public void unlinkInd(CusIndLinkDto cusIndLinkDto) {
        CusIndLinkDto cusIndLinkDtoOld = getLinkInd(cusIndLinkDto.getCusId(), cusIndLinkDto.getIndId());
        if (cusIndLinkDtoOld == null) {
            throw new ScoreException("ind link info do not exist");
        }
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("cus_id", cusIndLinkDto.getCusId());
        wrapper.eq("ind_id", cusIndLinkDto.getIndId());
        cusIndLinkMapper.delete(wrapper);
        CusIndUnlinkEvent cusIndUnlinkEvent = new CusIndUnlinkEvent(this);
        BeanUtils.copyProperties(cusIndLinkDtoOld, cusIndUnlinkEvent);
        applicationEventPublisher.publishEvent(cusIndUnlinkEvent);
    }
}
